import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.awt.*;
import java.net.*;

/**
 * Creates Server by prompting for required input using an input GUI.
 * Then creates a Server GUI.
 *
 * @author BluJaded Team
 * @version (see Sourceforge.net)
 */
public class ServerGui implements Runnable, MouseListener, WindowListener {
    
    // an Internet Address object ussed to retrieve and hold the localhost details of the Server Machine
    private InetAddress addr;
    
    // the JFrame of the input GUI
    private JFrame inputFrame;
    
    // JTextField to input a port number
    private JTextField portT;
    
    // Jbutton to accept and procces the input supplied
    private JButton acceptB;
    
    // String to hold the port number supplied to pass to the main method of Server
    private String port;

    /**
     * the JFrame of the Server GUI.
     */
    public static JFrame Sframe;
    
    // Jbutton to terminate the execution of the Server smoothly
    private JButton terminateB;
    
    // a thread variable to hold the thread of the Server GUI that starts the server
    private Thread runServer;
    
    // JLabel to display the number of currently connected Clients
    private static JLabel handleCount;

    /**
     * Creates GUI to input the arguments the Server requires to run.
     */
    private ServerGui()
    {
        inputFrame = new JFrame("New Server");

        Container contentPane = inputFrame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        Container inputPanel = new JPanel();
        inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
        portT = new JTextField("1352");
        inputPanel.add (new JLabel ("Please specify a port for"));
        inputPanel.add (new JLabel ("Jadetalk to use:"));
        inputPanel.add(portT);
        acceptB = new JButton("Accept");
        acceptB.addMouseListener (this);
        contentPane.add (acceptB, BorderLayout.SOUTH);
        contentPane.add(new JLabel ("       "), BorderLayout.WEST);
        contentPane.add(new JLabel ("       "), BorderLayout.EAST);
        contentPane.add(inputPanel, BorderLayout.CENTER);
        inputFrame.addWindowListener(this);
        inputFrame.setResizable(false);
        inputFrame.pack();
        inputFrame.setVisible(true);


    }

    /**
     * Updates the number of currently connected clients.
     */
    public static void updateClientCount()
    {
        handleCount.setText(ClientHandler.handlers.size() +" of 20 Clients Currently Connected.");
        Sframe.validate();
    }

    /**
     * Creates the Server GUI.
     */
    private void makeServerGUI(){
        try{
            addr = InetAddress.getLocalHost();
        }
        catch (UnknownHostException e){}

        Sframe = new JFrame("JadeTalk Server Running on " + addr.toString());

        Container contentPane = Sframe.getContentPane();
        contentPane.setLayout(new BorderLayout());
        terminateB = new JButton("Terminate Server");
        terminateB.addMouseListener (this);
        contentPane.add (terminateB, BorderLayout.SOUTH);
        contentPane.add(new JLabel ("       "), BorderLayout.WEST);
        contentPane.add(new JLabel ("       "), BorderLayout.EAST);
        JLabel label = new JLabel("Server Running on " + addr.toString()+ " ...");
        label.setHorizontalAlignment(0);
        contentPane.add(label, BorderLayout.CENTER);
        handleCount = new JLabel();
        updateClientCount();
        handleCount.setHorizontalAlignment(0);
        contentPane.add(handleCount, BorderLayout.CENTER);
        Sframe.addWindowListener(this);
        Sframe.setResizable(false);
        Sframe.pack();
        Sframe.setVisible(true);
        if(inputFrame.isVisible()){
            inputFrame.dispose();
        }
    }


   /**
    * mouseClicked Event occurs when the mouse if clicked on a listening object.
    * 
    * @param      e    the mouseEvent object assosiated with the event.
    */
    public void mouseClicked(MouseEvent e) {
        
        // if the terminate button on the Server GUI was pressed
        if (e.getSource().equals(terminateB)){
            // terminate the server smoothly
            Server.terminateServer();
            // closes the window by disposing of the frame.
            Sframe.dispose();
        }
        
        // if the accept button on the input GUI was pressed
        if (e.getSource().equals(acceptB)){
            // Get port number from textfield
            port = portT.getText();
            try {
                // Turn port number String into an int
                int portNum = Integer.parseInt(portT.getText());
                // if the port number provided is between 1024 and 49151
                if(portNum >= 1024 && portNum <= 49151){
                    
                    // closes the window by disposing of the frame.
                    inputFrame.dispose();
                    // creates a new thread associated with this object
                    runServer = new Thread(this);
                    // starts that thread
                    runServer.start();
                    // makes the Server Gui
                    makeServerGUI();
                }
                else{
                    // display a message box to give the user feedback on their incorrect input
                    JOptionPane.showMessageDialog(inputFrame, 
                          "You must provide a valid and free port number between 1024 and 49151.",
                          "Invalid Port Number", 
                          JOptionPane.INFORMATION_MESSAGE);
                }
            }
            catch (NumberFormatException ex) {
                // if the input in port field is not recognised as an integer
                // display a message box to give the user feedback on their incorrect input
                JOptionPane.showMessageDialog(inputFrame,
                      "You must provide a valid and free port number between 1024 and 49151. ",
                      "Invalid Port Number",
                      JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }



   

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void mousePressed(MouseEvent e) {}

    public void mouseReleased(MouseEvent e)  {}

    public void windowActivated(WindowEvent e)  {}

    public void windowClosed(WindowEvent e)  {}

    /**
     * windowClosing Event occurs when the window is closed by the user or program.
     *
     * @param      e    the WindowEvent object assosiated with the event.
     **/
    public void windowClosing(WindowEvent e)  {
        // If Server window is closed then quit Server
        if (e.getSource().equals(Sframe)){
            Server.terminateServer();
            Sframe.dispose();
        }

        // If server Input window is shut then quit input mechanism
        if (e.getSource().equals(inputFrame)){
            inputFrame.dispose();
            System.exit(0);
        }
    }

    public void windowDeactivated(WindowEvent e)  {}

    public void windowDeiconified(WindowEvent e)  {}

    public void windowIconified(WindowEvent e)  {}

    public void windowOpened(WindowEvent e)  {}

    /**
     * Run method required by the implementation of Runnable is executed when a new thread, once created, is started.
     * Runs the Servers main method and passes it the port given by the user
     */
    public void run () {
         try{
            Server.main(new String[]{port});
         }
         catch (IOException er) {
            // if an error occurs prints the stack trace to assist debugging
            // ex.printStackTrace();
         }
    }

    /**
     * main method provides an execution start and allows commandline execution.
     *
     * @param args The standard commandline arguments parameter.
     */
    public static void main(String[] args)
    {
        new ServerGui();
    }
}